#include <ctime>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <thread>

/*
这是一个基于 Boost.Asio 的异步 TCP 服务器实现，主要功能是向连接的客户端发送当前时间。主要组件包括：
make_daytime_string(): 生成当前时间字符串
tcp_connection: 处理单个客户端连接的类
tcp_server: 管理服务器并接受新连接的类
服务器使用异步操作处理连接，这样可以同时服务多个客户端而不需要使用多线程。
服务器监听 13 端口（标准的 daytime 服务端口），当有新的连接时，会发送当前时间给客户端。
*/
using boost::asio::ip::tcp;

// 生成当前时间字符串
std::string make_daytime_string()
{
    using namespace std; // 使用标准命名空间中的 time_t, time 和 ctime
    time_t now = time(0);
    return ctime(&now);
}

// TCP连接类，继承自 enable_shared_from_this 以安全地使用 shared_ptr
class tcp_connection
    : public std::enable_shared_from_this<tcp_connection>
{
public:
    // 定义指向 tcp_connection 的智能指针类型
    typedef std::shared_ptr<tcp_connection> pointer;

    // 创建 TCP 连接的工厂方法
    static pointer create(boost::asio::io_context &io_context)
    {
        return pointer(new tcp_connection(io_context));
    }

    // 获取套接字引用
    tcp::socket &socket()
    {
        return socket_;
    }

    // 开始处理连接
    void start()
    {
        message_ = make_daytime_string();

        // 异步写入时间信息到客户端
        boost::asio::async_write(socket_, boost::asio::buffer(message_),
                                 boost::bind(&tcp_connection::handle_write, shared_from_this(),
                                             boost::asio::placeholders::error,
                                             boost::asio::placeholders::bytes_transferred));
    }

private:
    // 私有构造函数，只能通过 create 方法创建对象
    tcp_connection(boost::asio::io_context &io_context)
        : socket_(io_context)
    {
    }

    // 写入完成后的回调处理
    void handle_write(const boost::system::error_code & /*error*/,
                      size_t /*bytes_transferred*/)
    {
    }

    tcp::socket socket_;  // 套接字对象
    std::string message_; // 要发送的消息
};

// TCP服务器类
class tcp_server
{
public:
    // 构造函数，初始化服务器并开始监听端口13
    tcp_server(boost::asio::io_context &io_context)
        : io_context_(io_context),
          acceptor_(io_context, tcp::endpoint(tcp::v4(), 13133))
    {
        start_accept();
    }

private:
    // 开始接受新的连接
    void start_accept()
    {
        // 创建新的连接对象
        tcp_connection::pointer new_connection =
            tcp_connection::create(io_context_);

        // 异步等待并接受新的连接
        acceptor_.async_accept(new_connection->socket(),
                               boost::bind(&tcp_server::handle_accept, this, new_connection,
                                           boost::asio::placeholders::error));
    }

    // 处理新接受的连接
    void handle_accept(tcp_connection::pointer new_connection,
                       const boost::system::error_code &error)
    {
        if (!error)
        {
            new_connection->start(); // 开始处理新连接
        }

        start_accept(); // 继续接受下一个连接
    }

    boost::asio::io_context &io_context_; // IO上下文引用
    tcp::acceptor acceptor_;              // 接受器对象
};

// 主函数
int main()
{
    try
    {
        boost::asio::io_context io_context;
        tcp_server server(io_context); // 创建服务器实例

        std::thread t([&io_context]()
                      { io_context.run(); });

        std::cout << "服务器正在运行..." << std::endl;
        std::cout << "监听端口: 13133" << std::endl;
        std::cout << "线程ID: " << std::this_thread::get_id() << std::endl;

        // 打印
        t.join();

        std::cout << "服务器结束..." << std::endl;
        std::cout << "监听端口: 13133" << std::endl;
        std::cout << "线程ID: " << std::this_thread::get_id() << std::endl;
    }
    catch (std::exception &e)
    {

        std::cerr << e.what() << std::endl;
    }

    return 0;
}